package com.zndroid.utils.impl;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;

import java.io.File;
import java.util.List;

/**
 * @name:AppUtil
 * @author:lazy
 * @email:luzhenyuxfcy@sina.com
 * @date : 2020/7/19 22:33
 * @version:
 * @description:APP属性相关
 */
@SuppressWarnings("unused")
public class AppUtil {
    private final String TAG = AppUtil.class.getSimpleName();

    /**
     * Gets the version name in the manifest file
     * @param context context
     * @return String
     */
    @NonNull
    public String getVersionName(@Nullable Context context) {
        String versionName = "unknown";
        if (context == null) {
            return versionName;
        }
        try {
            versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException ex) {
            Log.e(TAG, "Package Not found:" + context.getPackageName());
        }
        return versionName;
    }

    /**
     * Gets the version code in the manifest file
     * @param context context
     * @return long
     */
    public long getVersionCode(@Nullable Context context) {
        long versionCode = -1;
        if (context == null) {
            return versionCode;
        }
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).getLongVersionCode();
            } else {
                versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
            }
        } catch (PackageManager.NameNotFoundException ex) {
            Log.e(TAG, "Package Not found:" + context.getPackageName());
        }
        return versionCode;
    }

    /**
     * 对一个apk文件获取相应的信息
     *
     * @param context context
     * @param path    apk路径
     */
    public long getVersionCode(Context context, String path) {
        long versionCode = -1;
        if (context == null || TextUtils.isEmpty(path)) {
            return versionCode;
        }
        File file = new File(path);

        if (file.exists() && file.length() > 0) {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
            if (packageInfo != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    return packageInfo.getLongVersionCode();
                } else {
                    return packageInfo.versionCode;
                }
            } else {
                return versionCode;
            }
        }
        return versionCode;
    }

    public String getVersionName(Context context, String path) {
        String versionName = "unknown";
        if (context == null || TextUtils.isEmpty(path)) {
            return versionName;
        }
        File file = new File(path);

        if (file.exists() && file.length() > 0) {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
            if (packageInfo != null) {
                return packageInfo.versionName;
            } else {
                return versionName;
            }
        }
        return versionName;
    }

    public String getPackageName(Context context, String path) {
        String packageName = "unknown";
        if (context == null || TextUtils.isEmpty(path)) {
            return packageName;
        }
        File file = new File(path);

        if (file.exists() && file.length() > 0) {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
            if (packageInfo != null) {
                return packageInfo.packageName;
            } else {
                return packageName;
            }
        }
        return packageName;
    }

    /**
     * Gets the application name specified by android:label in the AndroidManifest.xml.
     * It does not work if you hard-code your app name like android:label="MyApp".
     * Use a string resource such as @string/app_name.
     * @param context context
     * @return application name
     */
    public String getAppName(@NonNull Context context) {
        int stringId = context.getApplicationInfo().labelRes;
        return context.getString(stringId);
    }

    public long getFirstInstallTime(@NonNull Context context) {
        try {
            return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).firstInstallTime;
        } catch (PackageManager.NameNotFoundException e) {
            return -1;
        }

    }

    public long getLastUpdateTime(@NonNull Context context) {
        try {
            return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).lastUpdateTime;
        } catch (PackageManager.NameNotFoundException e) {
            return -1;
        }

    }

    /**
     * Checks if the target app is installed on the device
     * @param context context
     * @param targetPackageName PackageName
     * @return boolean
     */
    public boolean isAppInstalled(@NonNull Context context, String targetPackageName) {
        PackageManager pm = context.getPackageManager();

        @SuppressLint("QueryPermissionsNeeded")
        List<PackageInfo> list = pm.getInstalledPackages(0);
        for (PackageInfo info : list) {
            if (targetPackageName.equals(info.packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if an activity with the given intent is successfully started
     * @param context context
     * @param intent intent
     * @return true or false
     */
    public boolean startActivity(@NonNull Context context, Intent intent) {
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException ae) {
            return false;
        }

        return true;
    }

    /**
     * 重启当前APP
     * */
    public void restartApp(@NonNull Context context) {
        Intent intent = context.getApplicationContext().getPackageManager().getLaunchIntentForPackage(context.getPackageName());
        if (null != intent) {
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            @SuppressLint("UnspecifiedImmutableFlag")
            PendingIntent restartIntent = PendingIntent.getActivity(context.getApplicationContext(), 0, intent, android.app.PendingIntent.FLAG_ONE_SHOT);

            AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            alarmManager.set(AlarmManager.RTC, 500, restartIntent);

            System.exit(0);
        }
    }

    /**
     * get PackageName of current app
     * @param context context
     * */
    public String getPackageName(Context context) {
        String packageName = "";
        try {
            PackageManager packageManager = context.getPackageManager();
            packageName = packageManager.getPackageInfo(context.getPackageName(), 0).packageName;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return packageName;
    }

    /**
     * install '.apk' use system installer
     * @param context context
     * @param path local apk path suffix with '.apk'
     * */
    public void installApk(Context context, String path, @NonNull String authority) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        File file = new File(path);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Uri apkUri = FileProvider.getUriForFile(context, authority, file);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            Uri uri = Uri.fromFile(file);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        }
        context.startActivity(intent);
    }

    /**
     * 获取 'AndroidManifest.xml' 中 'meta-data' 定义
     * @param context context
     * */
    public Bundle getAppMetaData(Context context) {
        PackageManager pm = context.getPackageManager();
        ApplicationInfo info = null;
        try {
            info = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return info != null ? info.metaData : null;
    }

    /**
     * 获取铃声音量，需要WRITE_APN_SETTINGS权限
     *
     * @param context 上下文
     * @return 铃声音量，取值范围为0-7；默认为0
     */
    public int getRingVolume(Context context) {
        return ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)).getStreamVolume(AudioManager.STREAM_RING);
    }

    /**
     * 设置铃声音量
     *
     * @param context 上下文
     */
    public void setRingVolume(Context context, @IntRange(from = 0, to = 7) int ringVolume) {
        if (ringVolume < 0) {
            ringVolume = 0;
        } else if (ringVolume > 7) {
            ringVolume = ringVolume % 7;
            if (ringVolume == 0) {
                ringVolume = 7;
            }
        }

        ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)).setStreamVolume(AudioManager.STREAM_RING,
                ringVolume, AudioManager.FLAG_PLAY_SOUND);
    }
}
